library(cluster)
package ‘cluster’ was built under R version 3.4.4
library(mclust)
package ‘mclust’ was built under R version 3.4.4    __  ___________    __  _____________
   /  |/  / ____/ /   / / / / ___/_  __/
  / /|_/ / /   / /   / / / /\__ \ / /   
 / /  / / /___/ /___/ /_/ /___/ // /    
/_/  /_/\____/_____/\____//____//_/    version 5.4.1
Type 'citation("mclust")' for citing this R package in publications.
library(lattice)
library(tidyverse)
package ‘tidyverse’ was built under R version 3.4.2── Attaching packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 2.2.1.9000     ✔ purrr   0.2.4     
✔ tibble  1.4.2          ✔ dplyr   0.7.5     
✔ tidyr   0.8.1          ✔ stringr 1.3.1     
✔ readr   1.1.1          ✔ forcats 0.3.0     
package ‘tibble’ was built under R version 3.4.3package ‘purrr’ was built under R version 3.4.2package ‘forcats’ was built under R version 3.4.3── Conflicts ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
✖ purrr::map()    masks mclust::map()
library(maptree)
Loading required package: rpart
package ‘rpart’ was built under R version 3.4.3
library(mice)
package ‘mice’ was built under R version 3.4.4
Attaching package: ‘mice’

The following object is masked from ‘package:tidyr’:

    complete

The following objects are masked from ‘package:base’:

    cbind, rbind
library(magrittr)

Attaching package: ‘magrittr’

The following object is masked from ‘package:purrr’:

    set_names

The following object is masked from ‘package:tidyr’:

    extract
library(mclust)
library(mice)
library(nFactors)
Loading required package: MASS

Attaching package: ‘MASS’

The following object is masked from ‘package:dplyr’:

    select

Loading required package: psych

Attaching package: ‘psych’

The following objects are masked from ‘package:ggplot2’:

    %+%, alpha

The following object is masked from ‘package:mclust’:

    sim

Loading required package: boot
package ‘boot’ was built under R version 3.4.1
Attaching package: ‘boot’

The following object is masked from ‘package:psych’:

    logit

The following object is masked from ‘package:lattice’:

    melanoma


Attaching package: ‘nFactors’

The following object is masked from ‘package:lattice’:

    parallel
library(poLCA)
Loading required package: scatterplot3d
package ‘scatterplot3d’ was built under R version 3.4.4
library(Rtsne)
library(corrplot)
package ‘corrplot’ was built under R version 3.4.2corrplot 0.84 loaded

1 Utility Functions

utility_histogramplotter <- function(x) {
  lattice::histogram( ~ x)
}
seg.summ <- function(data, groups) {
  aggregate(data, list(groups), function(x) mean(as.numeric(as.character(x))))
}
minmax <- function(x)
{
    return((x- min(x)) /(max(x)-min(x)))
}
plot_bi_plots <- function(df, y,...) {
  old.par = par()
  par(mar=c(5,4,5,2))
  on.exit(expr = 'par = old.par')
  prcomp(df) %>% biplot(col = c('gray', 'red'), cex = .8, main = y, ...)
}
adjust_q13 <- function(df){
  df %<>% 
    mutate(q13_visitfreq_social= (q13r1+q13r2+q13r3 +q13r11)/4,
           q13_visitfreq_music = (q13r4+q13r7+q13r8 +q13r9)/4,
           q13_visitfreq_video = (q13r5+q13r6+q13r10+q13r12)/4)
  df[,!str_detect(names(df),'q13r')]
}
adjust_q24 <- function(df){
  df %<>% 
    mutate(
      q24_tech_posatt = (q24r1+q24r2+q24r3+q24r5+q24r6)/5,
      q24_tech_enter = (q24r7+q24r8)/2,
      q24_tech_comm = (q24r10+q24r11+q24r12)/3,
      q24_tech_negatv = (q24r4+q24r9)/2
    )
  df[,!str_detect(names(df),'q24r')]
}
adjust_q25 <- function(df){
  df %<>% 
    mutate(
      q25_prsnlty_leader = (q25r1+q25r2+q25r3+q25r4)/4,
      q25_prsnlty_risk   = (q25r5+q25r7+q25r8)/3,
      q25_prsnlty_drive  = (q25r9+q25r10+q25r11+q25r12)/4,
      q25_prsnlty_follower = q25r6
    )
  df[,!str_detect(names(df),'q25r')]
}
adjust_q26 <- function(df){
  df %<>% 
    mutate(
      q26_shopsavvy_bargain =  (q26r3+q26r5)/2,
      q26_shopsavvy_brands = (q26r18+q26r7+q26r13+q26r14+q26r15)/5,
      q26_shopsavvy_earn2spend = (q26r13+q26r16+q26r4)/3,
      q26_shopsavvy_applover = (q26r17+q26r12+q26r10+q26r8+q26r6+q26r9)/6,
      q26_shopsavvy_children = q26r11,
    )
  df[,!str_detect(names(df),'q26r')]
}
adjust_q2 <- function(df){
  df %<>%
    mutate(
      q2_apple = ifelse(q2r1==1|q2r2==1,1,0),
      q2_andriod = q2r3,
      q2_windows = q2r6,
      q2_tablet = q2r8,
      q2_other = ifelse(q2r4==1|q2r5==1|q2r7==1|q2r9==1,1,0)
    )
  df[,!str_detect(names(df),'q2r')]
}
adjust_q4 <- function(df){
    df %<>%
    mutate(
      q4_use_music_apps =q4r1,
      q4_use_tv_apps =ifelse(q4r2==1|q4r3==1|q4r4==1,1,0),
      q4_use_game_apps =q4r5,
      q4_use_social_apps =q4r6,
      q4_use_news_apps =ifelse(q4r7==1|q4r9==1,1,0),
      q4_use_shop_apps =q4r8,
      q4_use_none_apps =q4r11
    )
  df[,!str_detect(names(df),'q4r')]
}
adjust_race <- function(df){
  df %>% 
    mutate(
      q54_white  = ifelse(q54==1,1,0),
      q54_black  = ifelse(q54==2,1,0),
      q54_asian  = ifelse(q54==3,1,0),
      q54_hawai  = ifelse(q54==4,1,0),
      q54_native =  ifelse(q54==5,1,0),
      q54_other  = ifelse(q54==6,1,0),
      q55_latino =  ifelse(q55==1,1,0)
    ) %>% 
    dplyr::select(-q54,-q55)
}
adjust_gender <- function(df){
  df %>% 
    mutate(q57 = ifelse(q57==1,1,0))
}
adjust_marital <- function(df){
  df %>% 
    mutate(q49 = ifelse(q49==1,1,0))
}
adjust_q11 <- function(df){
  #Q11 has artificial ordinality between #of apps increasing, and response==5 as "Dont know"
  #This function resolves this problem
  df %>% 
    mutate(q11 = ifelse(q11==5 | q11==6, 0, q11))
}
adjust_children <- function(df){
  df %>% 
    dplyr::select(-q50r2_inftod,-q50r3_6_12,-q50r4_13_17,-q50r5_adult)
}
adjust_income <- function(df){
  df %>% 
    dplyr::mutate(q56 = case_when(
      q56 <= 4 ~ 1,
      q56 >= 5 & q56 <=8 ~ 2,
      q56 >= 9 & q56 <=11 ~ 3,
      q56 >= 12 & q56 <= 13 ~ 4,
      q56 >= 14 ~ 5
    ))
}
adjust_age <- function(df){
  df %>% 
    dplyr::mutate(
      q1 = case_when(
        q1 <= 2 ~ 1,
        q1 >= 3 & q1 <= 5 ~ 2,
        q1 >= 6 & q1 <= 8 ~ 3,
        q1 >= 9 & q1 <= 11 ~ 4,
        q1 >= 12 ~ 5,
      )
    )
}
adjust_names <- function(df){
  df %>% 
    dplyr::rename(
      q1_age=q1,
      q11_appnum = q11,
      q12_freeapppc = q12,
      q48_edu = q48,
      q49_marital = q49,
      q56_income = q56,
      q57_mf = q57,
      q50r1_nochild = q50r1,
      q50r2_inftod = q50r2, 
      q50r3_6_12 = q50r3,
      q50r4_13_17 = q50r4,
      q50r5_adult = q50r5
    )
}

2 Data Prep

load('../data/apphappyData.RData')
df_labs <- tbl_df(apphappy.3.labs.frame)
df_nums <- tbl_df(apphappy.3.num.frame)
dim(df_nums)
[1] 1800   89
rm(apphappy.3.num.frame); rm(apphappy.3.labs.frame)
df_labs$q57 <- as.factor(df_labs$q57)
df_labs$caseID <- NULL
df_nums$caseID <- NULL
df_labs$q2r10 <- NULL
df_nums$q2r10 <- NULL
df_labs$q5r1 <- NULL
df_nums$q5r1 <- NULL

3 Remove missing values

3.1 Handle the case of the missing apps?

df_nums$q12[is.na(df_nums$q12)] <- 0
df_nums %>% xtabs(~q12+q11,.,addNA = T)
   q11
q12   1   2   3   4   5   6
  0   0   0   0   0   0  24
  1   6   9   5   3   1   0
  2  31  56  48  66   2   0
  3  23  42 117 114  11   0
  4  12  44 150 198  12   0
  5  23  44 158 209  20   0
  6  68  78 131  71  24   0
df_nums %>% xtabs(~q4r10+q11,.,addNA = T)
     q11
q4r10   1   2   3   4   5   6
    0 156 254 564 595  67  24
    1   7  19  45  66   3   0
df_nums %>% xtabs(~q4r11+q11,.,addNA = T)
     q11
q4r11   1   2   3   4   5   6
    0 148 267 606 661  65   8
    1  15   6   3   0   5  16
# RULE (A): IF q4r11=TRUE, it means you have no apps. So that means q11 has to equal 6, i.e. NONE. Data shows this is violated. Correcting using this rule.
df_nums$q11[df_nums$q4r11==TRUE] <- 6
df_nums %>% xtabs(~q4r11+q11,.,addNA = T)
     q11
q4r11   1   2   3   4   5   6
    0 148 267 606 661  65   8
    1   0   0   0   0   0  45

3.2 Small changes

Since q11 can be ordinal, “none” should equal 0 instead of 6 to preserve ordinality

# RULE (B): Set q11=6 to q11=0
df_nums$q11[df_nums$q11==6] <- 0
df_nums %>% xtabs(~q11,., addNA = T)
q11
  0   1   2   3   4   5 
 53 148 267 606 661  65 

‘Dont know’ doesn’t add value. Perhaps these can be set to NA and then imputed using mice.

# RULE (C): Set q11 Dont know to NA
df_nums$q11[df_nums$q11==0] <- NA
df_nums %>% xtabs(~q11,., addNA = T)
q11
   1    2    3    4    5 <NA> 
 148  267  606  661   65   53 
# RULE (D): All NA values for q12 set to 6, since I'm approximating that if you don't have any apps, might as well could as free?
df_nums$q12[is.na(df_nums$q12)] <- 6
df_nums %>% xtabs(~q12,., addNA = T)
q12
  0   1   2   3   4   5   6 
 24  24 203 307 416 454 372 
map_int(df_nums,~sum(is.na(.x))) %>% sort() %>% tail(3) %>% barchart(main='Missing values')

3.3 Imputing using mice

map_df(df_nums,~as.factor(.x)) %>% 
  mice::mice(printFlag = T, m = 5, method = 'rf') -> miceFit

 iter imp variable
  1   1  q11  q57
  1   2  q11  q57
  1   3  q11  q57
  1   4  q11  q57
  1   5  q11  q57
  2   1  q11  q57
  2   2  q11  q57
  2   3  q11  q57
  2   4  q11  q57
  2   5  q11  q57
  3   1  q11  q57
  3   2  q11  q57
  3   3  q11  q57
  3   4  q11  q57
  3   5  q11  q57
  4   1  q11  q57
  4   2  q11  q57
  4   3  q11  q57
  4   4  q11  q57
  4   5  q11  q57
  5   1  q11  q57
  5   2  q11  q57
  5   3  q11  q57
  5   4  q11  q57
  5   5  q11  q57
unknown timezone 'default/America/Indiana/Indianapolis'Number of logged events: 25
df_nums <- tbl_df(mice::complete(miceFit))

4 Bi Plots

# questions_to_consolidate <- c('q13','q24','q25','q26')
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[1])),questions_to_consolidate[1])
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[2])),questions_to_consolidate[2], xlim=c(0,.05), ylim=c(-0.01,0.002))
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[3])),questions_to_consolidate[3])
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[4])),questions_to_consolidate[4], xlim=c(0,0.05),ylim=c(-0.011,0.005))

5 Data Prep

5.1 Sub grouping

df_nums <- map_df(df_nums,~as.numeric(as.character(.x)))
df_nums_adj <- df_nums %>%  
  adjust_q13() %>% 
  adjust_q24() %>% 
  adjust_q25() %>% 
  adjust_q26() %>% 
  adjust_q2() %>% 
  adjust_q4() %>% 
  adjust_race() %>% 
  adjust_gender() %>% 
  adjust_marital() %>% 
  adjust_income() %>%
  adjust_age() %>% 
  adjust_q11() %>% 
  adjust_names() %>% 
  adjust_children()
package ‘bindrcpp’ was built under R version 3.4.4
glimpse(df_nums_adj)
Observations: 1,800
Variables: 43
$ q1_age                   <dbl> 1, 1, 3, 1, 2, 1, 2, 2, 2, 2, 2, 1, 1, 3, 1, 3, 2, 2, 1, 2, 1, 2, 4, 3, 2, 1, 1, 2, 2, 1, 2, 3, 2, 3, 1, 1, 2, 1, 1, 2, 2, 1, 2, 3, 2, 4, 2,...
$ q11_appnum               <dbl> 4, 3, 3, 4, 3, 4, 4, 3, 1, 2, 3, 2, 4, 4, 4, 3, 4, 3, 4, 4, 2, 4, 1, 4, 4, 1, 3, 3, 3, 4, 3, 4, 3, 1, 2, 3, 2, 4, 4, 0, 4, 3, 4, 3, 4, 4, 3,...
$ q12_freeapppc            <dbl> 5, 5, 6, 4, 6, 3, 3, 6, 5, 2, 5, 6, 2, 3, 5, 4, 2, 2, 3, 5, 3, 6, 2, 5, 4, 3, 4, 0, 4, 4, 3, 4, 5, 6, 6, 2, 6, 3, 5, 5, 3, 4, 2, 6, 4, 2, 6,...
$ q48_edu                  <dbl> 3, 4, 3, 4, 4, 1, 3, 4, 3, 3, 4, 3, 4, 3, 4, 3, 2, 4, 6, 6, 1, 5, 3, 4, 6, 1, 3, 2, 2, 3, 3, 3, 3, 4, 3, 2, 3, 3, 4, 2, 4, 3, 6, 4, 3, 4, 4,...
$ q49_marital              <dbl> 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1,...
$ q50r1_nochild            <dbl> 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0,...
$ q56_income               <dbl> 2, 3, 4, 2, 2, 1, 1, 3, 2, 2, 2, 2, 4, 3, 2, 4, 3, 2, 2, 2, 2, 4, 3, 3, 5, 1, 2, 2, 1, 2, 3, 3, 2, 3, 1, 2, 3, 1, 1, 2, 2, 2, 3, 1, 4, 5, 3,...
$ q57_mf                   <dbl> 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1,...
$ q13_visitfreq_social     <dbl> 2.50, 3.00, 3.25, 4.00, 2.50, 4.00, 2.50, 2.25, 2.75, 2.00, 2.75, 3.25, 1.25, 3.25, 2.00, 2.25, 2.75, 2.00, 2.75, 3.25, 3.25, 3.25, 4.00, 2....
$ q13_visitfreq_music      <dbl> 3.75, 3.50, 2.75, 3.25, 3.50, 3.50, 4.00, 2.50, 2.00, 1.25, 3.50, 3.25, 1.75, 3.25, 2.50, 3.75, 2.50, 2.75, 4.00, 3.25, 2.50, 2.50, 2.75, 3....
$ q13_visitfreq_video      <dbl> 2.50, 2.00, 2.50, 2.50, 1.75, 2.25, 3.25, 3.25, 2.00, 1.25, 3.50, 2.00, 1.50, 3.25, 2.25, 3.00, 1.75, 2.00, 3.25, 1.75, 3.25, 2.00, 3.25, 2....
$ q24_tech_posatt          <dbl> 2.8, 2.8, 3.0, 3.0, 2.2, 3.4, 2.8, 2.0, 2.6, 2.8, 2.2, 2.0, 1.4, 2.6, 2.8, 2.2, 1.0, 3.6, 1.0, 2.6, 1.0, 3.2, 4.4, 2.6, 2.0, 2.2, 1.0, 2.4, ...
$ q24_tech_enter           <dbl> 2.0, 2.0, 1.5, 3.0, 2.5, 1.0, 2.5, 2.0, 3.0, 2.5, 2.5, 1.0, 1.5, 2.0, 1.5, 1.5, 1.0, 1.5, 2.5, 2.5, 1.0, 1.0, 4.5, 2.0, 2.5, 3.0, 1.0, 4.5, ...
$ q24_tech_comm            <dbl> 2.666667, 1.333333, 2.666667, 3.666667, 3.333333, 1.000000, 3.000000, 2.333333, 3.000000, 2.333333, 4.333333, 1.000000, 2.000000, 1.666667, ...
$ q24_tech_negatv          <dbl> 1.0, 3.0, 4.5, 3.0, 1.5, 4.5, 1.5, 4.0, 4.5, 3.0, 5.5, 6.0, 2.0, 5.0, 3.5, 5.0, 1.0, 2.0, 4.0, 3.5, 1.0, 4.0, 4.0, 3.5, 2.0, 3.0, 1.0, 2.5, ...
$ q25_prsnlty_leader       <dbl> 1.50, 2.75, 2.50, 2.00, 3.25, 3.00, 3.00, 3.25, 2.75, 2.00, 2.00, 1.00, 1.25, 2.25, 1.50, 2.25, 1.25, 2.50, 1.75, 2.50, 2.75, 1.50, 4.75, 3....
$ q25_prsnlty_risk         <dbl> 1.666667, 2.333333, 3.333333, 2.666667, 3.666667, 3.000000, 1.666667, 3.000000, 3.000000, 2.333333, 2.666667, 1.333333, 1.333333, 3.000000, ...
$ q25_prsnlty_drive        <dbl> 2.75, 2.25, 2.00, 3.25, 3.00, 2.50, 2.50, 2.25, 2.75, 2.25, 3.00, 1.00, 1.75, 3.00, 1.50, 3.00, 2.25, 2.50, 1.50, 1.00, 2.25, 2.50, 2.00, 3....
$ q25_prsnlty_follower     <dbl> 5, 5, 6, 5, 4, 4, 2, 5, 5, 2, 6, 5, 2, 6, 5, 6, 3, 1, 4, 5, 3, 5, 6, 6, 2, 5, 1, 5, 5, 3, 4, 6, 4, 6, 6, 2, 5, 3, 4, 5, 5, 5, 6, 6, 6, 5, 3,...
$ q26_shopsavvy_bargain    <dbl> 2.5, 3.5, 3.0, 3.0, 3.0, 3.0, 3.5, 1.5, 3.5, 1.5, 2.5, 2.0, 1.5, 3.5, 3.5, 2.5, 1.0, 3.0, 3.5, 2.0, 3.5, 1.5, 3.5, 3.5, 2.5, 3.5, 1.0, 3.5, ...
$ q26_shopsavvy_brands     <dbl> 3.4, 3.2, 3.4, 3.0, 4.0, 3.2, 2.8, 3.8, 5.4, 1.4, 4.4, 3.6, 2.0, 3.6, 2.8, 4.6, 1.4, 2.0, 2.0, 3.0, 3.6, 4.6, 4.0, 4.4, 2.0, 4.6, 1.0, 5.8, ...
$ q26_shopsavvy_earn2spend <dbl> 2.666667, 3.333333, 3.666667, 3.666667, 4.000000, 4.000000, 5.000000, 3.000000, 5.333333, 1.000000, 3.666667, 3.666667, 2.333333, 4.333333, ...
$ q26_shopsavvy_applover   <dbl> 4.166667, 3.000000, 4.166667, 2.166667, 3.666667, 2.166667, 3.000000, 4.000000, 4.833333, 1.666667, 4.166667, 3.000000, 2.000000, 2.666667, ...
$ q26_shopsavvy_children   <dbl> 6, 6, 4, 6, 3, 5, 5, 6, 5, 1, 6, 6, 1, 3, 6, 2, 1, 3, 1, 4, 5, 6, 3, 5, 2, 5, 1, 6, 5, 5, 3, 4, 2, 3, 6, 2, 6, 6, 3, 4, 5, 3, 5, 3, 6, 5, 1,...
$ q2_apple                 <dbl> 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0,...
$ q2_andriod               <dbl> 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1,...
$ q2_windows               <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,...
$ q2_tablet                <dbl> 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,...
$ q2_other                 <dbl> 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,...
$ q4_use_music_apps        <dbl> 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
$ q4_use_tv_apps           <dbl> 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0,...
$ q4_use_game_apps         <dbl> 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0,...
$ q4_use_social_apps       <dbl> 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
$ q4_use_news_apps         <dbl> 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1,...
$ q4_use_shop_apps         <dbl> 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,...
$ q4_use_none_apps         <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q54_white                <dbl> 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
$ q54_black                <dbl> 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q54_asian                <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q54_hawai                <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q54_native               <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q54_other                <dbl> 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q55_latino               <dbl> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...

5.2 Selection of basis variables

set1 <- c(
  'q1_age',
  # 'q11_appnum',
  # 'q12_freeapppc',
  'q48_edu',
  'q49_marital',
  'q50r1_nochild',
  'q56_income',
  # 'q57_mf',
  # 'q13_visitfreq_social',
  # 'q13_visitfreq_music',
  # 'q13_visitfreq_video',
  'q24_tech_posatt',
  'q24_tech_enter',
  'q24_tech_comm',
  'q24_tech_negatv',
  # 'q25_prsnlty_leader',
  # 'q25_prsnlty_risk',
  # 'q25_prsnlty_drive',
  # 'q25_prsnlty_follower',
  'q26_shopsavvy_bargain',
  'q26_shopsavvy_brands',
  'q26_shopsavvy_earn2spend',
  'q26_shopsavvy_applover',
  'q26_shopsavvy_children',
  'q2_apple',
  'q2_andriod',
  'q2_windows',
  # 'q2_tablet',
  # 'q2_other',
  # 'q4_use_music_apps',
  # 'q4_use_tv_apps',
  # 'q4_use_game_apps',
  # 'q4_use_social_apps',
  # 'q4_use_news_apps',
  # 'q4_use_shop_apps',
  # 'q4_use_none_apps',
  'q54_white',
  'q54_black',
  'q54_asian',
  'q54_hawai',
  'q54_native',
  # 'q54_other',
  'q55_latino'
  )
set2 <- c(
  'q1_age',
  # 'q11_appnum',
  'q12_freeapppc',
  'q48_edu',
  'q49_marital',
  'q50r1_nochild',
  'q56_income',
  # 'q57_mf',
  'q13_visitfreq_social',
  'q13_visitfreq_music',
  'q13_visitfreq_video',
  'q24_tech_posatt',
  'q24_tech_enter',
  'q24_tech_comm',
  'q24_tech_negatv',
  'q25_prsnlty_leader',
  'q25_prsnlty_risk',
  'q25_prsnlty_drive',
  'q25_prsnlty_follower',
  'q26_shopsavvy_bargain',
  'q26_shopsavvy_brands',
  'q26_shopsavvy_earn2spend',
  'q26_shopsavvy_applover',
  'q26_shopsavvy_children',
  # 'q2_apple',
  # 'q2_andriod',
  # 'q2_windows',
  # 'q2_tablet',
  # 'q2_other',
  # 'q4_use_music_apps',
  # 'q4_use_tv_apps',
  # 'q4_use_game_apps',
  # 'q4_use_social_apps',
  # 'q4_use_news_apps',
  # 'q4_use_shop_apps',
  # 'q4_use_none_apps',
  'q54_white',
  'q54_black',
  'q54_asian',
  'q54_hawai',
  'q54_native',
  # 'q54_other',
  'q55_latino'
  )
set3 <- c(
  'q1_age',
  'q11_appnum',
  'q12_freeapppc',
  'q48_edu',
  'q49_marital',
  'q50r1_nochild',
  'q56_income',
  'q57_mf',
  # 'q13_visitfreq_social',
  # 'q13_visitfreq_music',
  # 'q13_visitfreq_video',
  # 'q24_tech_posatt',
  # 'q24_tech_enter',
  # 'q24_tech_comm',
  # 'q24_tech_negatv',
  # 'q25_prsnlty_leader',
  # 'q25_prsnlty_risk',
  # 'q25_prsnlty_drive',
  # 'q25_prsnlty_follower',
  'q26_shopsavvy_bargain',
  'q26_shopsavvy_brands',
  'q26_shopsavvy_earn2spend',
  'q26_shopsavvy_applover',
  'q26_shopsavvy_children',
  'q2_apple',
  'q2_andriod',
  'q2_windows',
  'q2_tablet',
  'q2_other',
  'q4_use_music_apps',
  'q4_use_tv_apps',
  'q4_use_game_apps',
  'q4_use_social_apps',
  'q4_use_news_apps',
  'q4_use_shop_apps',
  'q4_use_none_apps'
  # 'q54_white',
  # 'q54_black',
  # 'q54_asian',
  # 'q54_hawai',
  # 'q54_native',
  # 'q54_other',
  # 'q55_latino'
  )
set4 <- c(
  'q1_age',
  # 'q11_appnum',
  # 'q12_freeapppc',
  # 'q48_edu',
  'q49_marital',
  'q50r1_nochild',
  'q56_income',
  'q57_mf',
  'q13_visitfreq_social',
  'q13_visitfreq_music',
  'q13_visitfreq_video',
  'q24_tech_posatt',
  'q24_tech_enter',
  'q24_tech_comm',
  'q24_tech_negatv',
  'q25_prsnlty_leader',
  'q25_prsnlty_risk',
  'q25_prsnlty_drive',
  'q25_prsnlty_follower',
  'q26_shopsavvy_bargain',
  'q26_shopsavvy_brands',
  'q26_shopsavvy_earn2spend',
  'q26_shopsavvy_applover',
  'q26_shopsavvy_children'
  # 'q2_apple',
  # 'q2_andriod',
  # 'q2_windows',
  # 'q2_tablet',
  # 'q2_other',
  # 'q4_use_music_apps',
  # 'q4_use_tv_apps',
  # 'q4_use_game_apps',
  # 'q4_use_social_apps',
  # 'q4_use_news_apps',
  # 'q4_use_shop_apps',
  # 'q4_use_none_apps'
  # 'q54_white',
  # 'q54_black',
  # 'q54_asian',
  # 'q54_hawai',
  # 'q54_native',
  # 'q54_other',
  # 'q55_latino'
  )
df_nums_adj_backup <- df_nums_adj
df_nums_adj <- df_nums_adj_backup
df_nums_adj <- df_nums_adj %>% dplyr::select(one_of(set4))

6 Scaling

scaling_wanted <- T
minmax_wanted <- F
if (scaling_wanted) {
  df_nums_adjscaled <- scale(df_nums_adj)
  centers <- attributes(df_nums_adjscaled)[[3]]
  spreads <- attributes(df_nums_adjscaled)[[4]]
  df_nums_adjscaled <- tbl_df(df_nums_adjscaled)
}
if(minmax_wanted){
  df_nums_adjscaled <- map_df(df_nums_adj, ~minmax(.x))
}
if(!scaling_wanted & !minmax_wanted){
  df_nums_adjscaled <- df_nums_adj
}
head(df_nums_adjscaled)

7 Correlation Plot

df_nums_adjscaled %>% cor() %>% corrplot(method = 'shade',tl.col = 'black',tl.cex = .9, order = 'hclust', hclust.method = 'ward.D2')

8 Dissimilarity Calculations

# ordered=c(1:4,11,13:28)
# symm_bin=c(6:10,12,29:47)
# df_nums_adjscaled[ordered] <- map_df(df_nums_adjscaled[ordered],~as.ordered(.x))
# df_nums_adjscaled[symm_bin] <- map_df(df_nums_adjscaled[symm_bin],~as.factor(.x))
distMat <- daisy(df_nums_adjscaled)
binary variable(s) 2, 3, 5 treated as interval scaled

9 Simple clustering

9.1 H clust

9.1.1 How cophenetic changes with clustering method?

methods <- c('complete','average','ward.D','ward.D2','median','mcquitty','centroid')
method_vs_cop <- map_dbl(methods,~cor(cophenetic(hclust(d = distMat, method = .x)), distMat))
names(method_vs_cop) <- methods
barchart(sort(method_vs_cop))

k = 6
hclustFit <- hclust(d = distMat, method = 'ward.D')
plot(hclustFit, labels = F)
rect.hclust(hclustFit, k=k, border="red")

hclust_segments <- cutree(hclustFit, k = k)
table(hclust_segments)
hclust_segments
  1   2   3   4   5   6 
341 412 333 217 126 371 
clusplot(df_nums_adjscaled, hclust_segments, color=TRUE, shade=TRUE, labels=4, lines=0, main="HClust plot")

seg.summ(df_nums_adj, hclust_segments) -> centroids
centroids
cutFit <- cutree(hclustFit, k)
plot(silhouette(cutFit,distMat))

k <- 2:10
widths <- NULL
for(k_ in k){
  hclustFit <- hclust(d = distMat, method = 'ward.D')
  cutFit <- cutree(hclustFit, k_)
  widths <- c(widths,mean(silhouette(cutFit,distMat)[,'sil_width']))
}
plot(k,widths,type='b')

cbind(k,widths)
       k     widths
 [1,]  2 0.13737473
 [2,]  3 0.08281616
 [3,]  4 0.06855129
 [4,]  5 0.06137392
 [5,]  6 0.05921532
 [6,]  7 0.06267068
 [7,]  8 0.06064109
 [8,]  9 0.05293374
 [9,] 10 0.04584471

9.2 K-means

9.2.1 How many clusters to use?

wssplot <- function(numsub, nc=15, seed=1111) {
  wss <- (nrow(numsub)-1)*sum(apply(numsub,2,var))
  for (i in 2:nc) {
    set.seed(seed)
    wss[i] <- sum(kmeans(numsub, centers=i, iter.max = 1e4)$withinss)}
  plot(1:nc, wss, type="b", xlab="Number of Clusters",
       ylab="Within groups sum of squares")}
wssplot(df_nums_adjscaled)

9.2.2 Solving the k-means model

k <- 2:10
widths <- NULL
for(k_ in k){
  clusterresults <- kmeans(x = df_nums_adjscaled, centers = k_, nstart = 30)
  widths <- c(widths,mean(silhouette(clusterresults$cluster,distMat)[,'sil_width']))
}
did not converge in 10 iterations
plot(k,widths,type='b')

cbind(k,widths)
       k     widths
 [1,]  2 0.15626749
 [2,]  3 0.10919911
 [3,]  4 0.10576895
 [4,]  5 0.10285049
 [5,]  6 0.09506744
 [6,]  7 0.09259923
 [7,]  8 0.08744827
 [8,]  9 0.08373856
 [9,] 10 0.08123470
# Using cluster centers from hclust:
seg.summ(df_nums_adjscaled, hclust_segments) -> kmeans_centroids
clusterresults <- kmeans(x = df_nums_adjscaled, centers = kmeans_centroids[,-1])
rsquare <- clusterresults$betweenss/clusterresults$totss
cat('\nWithin SS:',clusterresults$withinss,' Sizes:\n',clusterresults$size,'\nrsq:', rsquare)

Within SS: 4949.8 5143.576 3741.233 3415.204 2907.519 4511.912  Sizes:
 383 395 220 254 223 325 
rsq: 0.3470117
clusplot(df_nums_adjscaled, clusterresults$cluster, color=TRUE, shade=TRUE, labels=4, lines=0, main="K-means cluster plot")

plot(silhouette(clusterresults$cluster,distMat))

purrr::map2(kmeans_results, names(kmeans_results),
            ~bwplot(cluster~.x, kmeans_results,
                    main=.y))
$q1_age

$q49_marital

$q50r1_nochild

$q56_income

$q57_mf

$q13_visitfreq_social

$q13_visitfreq_music

$q13_visitfreq_video

$q24_tech_posatt

$q24_tech_enter

$q24_tech_comm

$q24_tech_negatv

$q25_prsnlty_leader

$q25_prsnlty_risk

$q25_prsnlty_drive

$q25_prsnlty_follower

$q26_shopsavvy_bargain

$q26_shopsavvy_brands

$q26_shopsavvy_earn2spend

$q26_shopsavvy_applover

$q26_shopsavvy_children

$cluster

9.3 PAM

pamFits <- tibble(k_pam = 2:10)
pamFits$pamFits <- map(pamFits$k_pam, ~pam(df_nums_adjscaled, k = .x))
pamFits$sil_avg_width <- map_dbl(pamFits$pamFits,~.x$silinfo$avg.width)
pamFits
pamFits %>% 
  xyplot(sil_avg_width~as.factor(k_pam),.,type='b')

plot(pamFits$pamFits[[1]])

seg.summ(df_nums_adj, pamFits$pamFits[[1]]$clustering)

10 Model based

mclustFits <- tibble(mclust_clusters=2:8)
mclustFits$mclustFits <- map(mclustFits$mclust_clusters, ~Mclust(df_nums_adjscaled, G = .x))
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
mclustFits$bic <- map_dbl(mclustFits$mclustFits, ~.x[['bic']])
mclustFits$loglik <- map_dbl(mclustFits$mclustFits, ~.x[['loglik']])
mclustFits
mclustFits %>% 
  xyplot(bic+loglik~as.factor(mclust_clusters),., auto.key = T, type = 'b')

summary(mclustFits[[4,'mclustFits']])
---------------------------------------------------- 
Gaussian finite mixture model fitted by EM algorithm 
---------------------------------------------------- 

Mclust VII (spherical, varying volume) model with 5 components: 

 log.likelihood    n  df       BIC       ICL
      -48851.89 1800 114 -98558.28 -98984.67

Clustering table:
  1   2   3   4   5 
527 317 305 275 376 
mclust_clusters <- mclustFits[[4,'mclustFits']]$classification
clusplot(df_nums_adj, mclust_clusters, color=TRUE, shade=TRUE, labels=4, lines=0, main="M Clust Plot, k = 4")

seg.summ(df_nums_adj, mclust_clusters)
mclust_distMat <- daisy(df_nums_adj)
binary variable(s) 2, 3, 5 treated as interval scaled
plot(silhouette(mclust_clusters,mclust_distMat))

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICBodG1sX25vdGVib29rOgogICAgaGlnaGxpZ2h0OiBlc3ByZXNzbwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBqb3VybmFsCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKYGBge3IgbGlicmFyaWVzfQpsaWJyYXJ5KGNsdXN0ZXIpCmxpYnJhcnkobWNsdXN0KQpsaWJyYXJ5KGxhdHRpY2UpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KG1hcHRyZWUpCmxpYnJhcnkobWljZSkKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShtY2x1c3QpCmxpYnJhcnkobWljZSkKbGlicmFyeShuRmFjdG9ycykKbGlicmFyeShwb0xDQSkKbGlicmFyeShSdHNuZSkKbGlicmFyeShjb3JycGxvdCkKYGBgCgojIFV0aWxpdHkgRnVuY3Rpb25zCmBgYHtyfQp1dGlsaXR5X2hpc3RvZ3JhbXBsb3R0ZXIgPC0gZnVuY3Rpb24oeCkgewogIGxhdHRpY2U6Omhpc3RvZ3JhbSggfiB4KQp9CnNlZy5zdW1tIDwtIGZ1bmN0aW9uKGRhdGEsIGdyb3VwcykgewogIGFnZ3JlZ2F0ZShkYXRhLCBsaXN0KGdyb3VwcyksIGZ1bmN0aW9uKHgpIG1lYW4oYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeCkpKSkKfQptaW5tYXggPC0gZnVuY3Rpb24oeCkKewogICAgcmV0dXJuKCh4LSBtaW4oeCkpIC8obWF4KHgpLW1pbih4KSkpCn0KcGxvdF9iaV9wbG90cyA8LSBmdW5jdGlvbihkZiwgeSwuLi4pIHsKICBvbGQucGFyID0gcGFyKCkKICBwYXIobWFyPWMoNSw0LDUsMikpCiAgb24uZXhpdChleHByID0gJ3BhciA9IG9sZC5wYXInKQogIHByY29tcChkZikgJT4lIGJpcGxvdChjb2wgPSBjKCdncmF5JywgJ3JlZCcpLCBjZXggPSAuOCwgbWFpbiA9IHksIC4uLikKfQphZGp1c3RfcTEzIDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPD4lIAogICAgbXV0YXRlKHExM192aXNpdGZyZXFfc29jaWFsPSAocTEzcjErcTEzcjIrcTEzcjMgK3ExM3IxMSkvNCwKICAgICAgICAgICBxMTNfdmlzaXRmcmVxX211c2ljID0gKHExM3I0K3ExM3I3K3ExM3I4ICtxMTNyOSkvNCwKICAgICAgICAgICBxMTNfdmlzaXRmcmVxX3ZpZGVvID0gKHExM3I1K3ExM3I2K3ExM3IxMCtxMTNyMTIpLzQpCiAgZGZbLCFzdHJfZGV0ZWN0KG5hbWVzKGRmKSwncTEzcicpXQp9CmFkanVzdF9xMjQgPC0gZnVuY3Rpb24oZGYpewogIGRmICU8PiUgCiAgICBtdXRhdGUoCiAgICAgIHEyNF90ZWNoX3Bvc2F0dCA9IChxMjRyMStxMjRyMitxMjRyMytxMjRyNStxMjRyNikvNSwKICAgICAgcTI0X3RlY2hfZW50ZXIgPSAocTI0cjcrcTI0cjgpLzIsCiAgICAgIHEyNF90ZWNoX2NvbW0gPSAocTI0cjEwK3EyNHIxMStxMjRyMTIpLzMsCiAgICAgIHEyNF90ZWNoX25lZ2F0diA9IChxMjRyNCtxMjRyOSkvMgogICAgKQogIGRmWywhc3RyX2RldGVjdChuYW1lcyhkZiksJ3EyNHInKV0KfQphZGp1c3RfcTI1IDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPD4lIAogICAgbXV0YXRlKAogICAgICBxMjVfcHJzbmx0eV9sZWFkZXIgPSAocTI1cjErcTI1cjIrcTI1cjMrcTI1cjQpLzQsCiAgICAgIHEyNV9wcnNubHR5X3Jpc2sgICA9IChxMjVyNStxMjVyNytxMjVyOCkvMywKICAgICAgcTI1X3Byc25sdHlfZHJpdmUgID0gKHEyNXI5K3EyNXIxMCtxMjVyMTErcTI1cjEyKS80LAogICAgICBxMjVfcHJzbmx0eV9mb2xsb3dlciA9IHEyNXI2CiAgICApCiAgZGZbLCFzdHJfZGV0ZWN0KG5hbWVzKGRmKSwncTI1cicpXQp9CmFkanVzdF9xMjYgPC0gZnVuY3Rpb24oZGYpewogIGRmICU8PiUgCiAgICBtdXRhdGUoCiAgICAgIHEyNl9zaG9wc2F2dnlfYmFyZ2FpbiA9ICAocTI2cjMrcTI2cjUpLzIsCiAgICAgIHEyNl9zaG9wc2F2dnlfYnJhbmRzID0gKHEyNnIxOCtxMjZyNytxMjZyMTMrcTI2cjE0K3EyNnIxNSkvNSwKICAgICAgcTI2X3Nob3BzYXZ2eV9lYXJuMnNwZW5kID0gKHEyNnIxMytxMjZyMTYrcTI2cjQpLzMsCiAgICAgIHEyNl9zaG9wc2F2dnlfYXBwbG92ZXIgPSAocTI2cjE3K3EyNnIxMitxMjZyMTArcTI2cjgrcTI2cjYrcTI2cjkpLzYsCiAgICAgIHEyNl9zaG9wc2F2dnlfY2hpbGRyZW4gPSBxMjZyMTEsCiAgICApCiAgZGZbLCFzdHJfZGV0ZWN0KG5hbWVzKGRmKSwncTI2cicpXQp9CmFkanVzdF9xMiA8LSBmdW5jdGlvbihkZil7CiAgZGYgJTw+JQogICAgbXV0YXRlKAogICAgICBxMl9hcHBsZSA9IGlmZWxzZShxMnIxPT0xfHEycjI9PTEsMSwwKSwKICAgICAgcTJfYW5kcmlvZCA9IHEycjMsCiAgICAgIHEyX3dpbmRvd3MgPSBxMnI2LAogICAgICBxMl90YWJsZXQgPSBxMnI4LAogICAgICBxMl9vdGhlciA9IGlmZWxzZShxMnI0PT0xfHEycjU9PTF8cTJyNz09MXxxMnI5PT0xLDEsMCkKICAgICkKICBkZlssIXN0cl9kZXRlY3QobmFtZXMoZGYpLCdxMnInKV0KfQphZGp1c3RfcTQgPC0gZnVuY3Rpb24oZGYpewogICAgZGYgJTw+JQogICAgbXV0YXRlKAogICAgICBxNF91c2VfbXVzaWNfYXBwcyA9cTRyMSwKICAgICAgcTRfdXNlX3R2X2FwcHMgPWlmZWxzZShxNHIyPT0xfHE0cjM9PTF8cTRyND09MSwxLDApLAogICAgICBxNF91c2VfZ2FtZV9hcHBzID1xNHI1LAogICAgICBxNF91c2Vfc29jaWFsX2FwcHMgPXE0cjYsCiAgICAgIHE0X3VzZV9uZXdzX2FwcHMgPWlmZWxzZShxNHI3PT0xfHE0cjk9PTEsMSwwKSwKICAgICAgcTRfdXNlX3Nob3BfYXBwcyA9cTRyOCwKICAgICAgcTRfdXNlX25vbmVfYXBwcyA9cTRyMTEKICAgICkKICBkZlssIXN0cl9kZXRlY3QobmFtZXMoZGYpLCdxNHInKV0KfQphZGp1c3RfcmFjZSA8LSBmdW5jdGlvbihkZil7CiAgZGYgJT4lIAogICAgbXV0YXRlKAogICAgICBxNTRfd2hpdGUgID0gaWZlbHNlKHE1ND09MSwxLDApLAogICAgICBxNTRfYmxhY2sgID0gaWZlbHNlKHE1ND09MiwxLDApLAogICAgICBxNTRfYXNpYW4gID0gaWZlbHNlKHE1ND09MywxLDApLAogICAgICBxNTRfaGF3YWkgID0gaWZlbHNlKHE1ND09NCwxLDApLAogICAgICBxNTRfbmF0aXZlID0gIGlmZWxzZShxNTQ9PTUsMSwwKSwKICAgICAgcTU0X290aGVyICA9IGlmZWxzZShxNTQ9PTYsMSwwKSwKICAgICAgcTU1X2xhdGlubyA9ICBpZmVsc2UocTU1PT0xLDEsMCkKICAgICkgJT4lIAogICAgZHBseXI6OnNlbGVjdCgtcTU0LC1xNTUpCn0KYWRqdXN0X2dlbmRlciA8LSBmdW5jdGlvbihkZil7CiAgZGYgJT4lIAogICAgbXV0YXRlKHE1NyA9IGlmZWxzZShxNTc9PTEsMSwwKSkKfQphZGp1c3RfbWFyaXRhbCA8LSBmdW5jdGlvbihkZil7CiAgZGYgJT4lIAogICAgbXV0YXRlKHE0OSA9IGlmZWxzZShxNDk9PTEsMSwwKSkKfQphZGp1c3RfcTExIDwtIGZ1bmN0aW9uKGRmKXsKICAjUTExIGhhcyBhcnRpZmljaWFsIG9yZGluYWxpdHkgYmV0d2VlbiAjb2YgYXBwcyBpbmNyZWFzaW5nLCBhbmQgcmVzcG9uc2U9PTUgYXMgIkRvbnQga25vdyIKICAjVGhpcyBmdW5jdGlvbiByZXNvbHZlcyB0aGlzIHByb2JsZW0KICBkZiAlPiUgCiAgICBtdXRhdGUocTExID0gaWZlbHNlKHExMT09NSB8IHExMT09NiwgMCwgcTExKSkKfQphZGp1c3RfY2hpbGRyZW4gPC0gZnVuY3Rpb24oZGYpewogIGRmICU+JSAKICAgIGRwbHlyOjpzZWxlY3QoLXE1MHIyX2luZnRvZCwtcTUwcjNfNl8xMiwtcTUwcjRfMTNfMTcsLXE1MHI1X2FkdWx0KQp9CmFkanVzdF9pbmNvbWUgPC0gZnVuY3Rpb24oZGYpewogIGRmICU+JSAKICAgIGRwbHlyOjptdXRhdGUocTU2ID0gY2FzZV93aGVuKAogICAgICBxNTYgPD0gNCB+IDEsCiAgICAgIHE1NiA+PSA1ICYgcTU2IDw9OCB+IDIsCiAgICAgIHE1NiA+PSA5ICYgcTU2IDw9MTEgfiAzLAogICAgICBxNTYgPj0gMTIgJiBxNTYgPD0gMTMgfiA0LAogICAgICBxNTYgPj0gMTQgfiA1CiAgICApKQp9CmFkanVzdF9hZ2UgPC0gZnVuY3Rpb24oZGYpewogIGRmICU+JSAKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIHExID0gY2FzZV93aGVuKAogICAgICAgIHExIDw9IDIgfiAxLAogICAgICAgIHExID49IDMgJiBxMSA8PSA1IH4gMiwKICAgICAgICBxMSA+PSA2ICYgcTEgPD0gOCB+IDMsCiAgICAgICAgcTEgPj0gOSAmIHExIDw9IDExIH4gNCwKICAgICAgICBxMSA+PSAxMiB+IDUsCiAgICAgICkKICAgICkKfQphZGp1c3RfbmFtZXMgPC0gZnVuY3Rpb24oZGYpewogIGRmICU+JSAKICAgIGRwbHlyOjpyZW5hbWUoCiAgICAgIHExX2FnZT1xMSwKICAgICAgcTExX2FwcG51bSA9IHExMSwKICAgICAgcTEyX2ZyZWVhcHBwYyA9IHExMiwKICAgICAgcTQ4X2VkdSA9IHE0OCwKICAgICAgcTQ5X21hcml0YWwgPSBxNDksCiAgICAgIHE1Nl9pbmNvbWUgPSBxNTYsCiAgICAgIHE1N19tZiA9IHE1NywKICAgICAgcTUwcjFfbm9jaGlsZCA9IHE1MHIxLAogICAgICBxNTByMl9pbmZ0b2QgPSBxNTByMiwgCiAgICAgIHE1MHIzXzZfMTIgPSBxNTByMywKICAgICAgcTUwcjRfMTNfMTcgPSBxNTByNCwKICAgICAgcTUwcjVfYWR1bHQgPSBxNTByNQogICAgKQp9CmBgYAoKCiMgRGF0YSBQcmVwCmBgYHtyfQpsb2FkKCcuLi9kYXRhL2FwcGhhcHB5RGF0YS5SRGF0YScpCmRmX2xhYnMgPC0gdGJsX2RmKGFwcGhhcHB5LjMubGFicy5mcmFtZSkKZGZfbnVtcyA8LSB0YmxfZGYoYXBwaGFwcHkuMy5udW0uZnJhbWUpCmRpbShkZl9udW1zKQpybShhcHBoYXBweS4zLm51bS5mcmFtZSk7IHJtKGFwcGhhcHB5LjMubGFicy5mcmFtZSkKZGZfbGFicyRxNTcgPC0gYXMuZmFjdG9yKGRmX2xhYnMkcTU3KQpkZl9sYWJzJGNhc2VJRCA8LSBOVUxMCmRmX251bXMkY2FzZUlEIDwtIE5VTEwKZGZfbGFicyRxMnIxMCA8LSBOVUxMCmRmX251bXMkcTJyMTAgPC0gTlVMTApkZl9sYWJzJHE1cjEgPC0gTlVMTApkZl9udW1zJHE1cjEgPC0gTlVMTApgYGAKCiMgUmVtb3ZlIG1pc3NpbmcgdmFsdWVzCgojIyBIYW5kbGUgdGhlIGNhc2Ugb2YgdGhlIG1pc3NpbmcgYXBwcz8KYGBge3J9CmRmX251bXMkcTEyW2lzLm5hKGRmX251bXMkcTEyKV0gPC0gMApkZl9udW1zICU+JSB4dGFicyh+cTEyK3ExMSwuLGFkZE5BID0gVCkKZGZfbnVtcyAlPiUgeHRhYnMofnE0cjEwK3ExMSwuLGFkZE5BID0gVCkKZGZfbnVtcyAlPiUgeHRhYnMofnE0cjExK3ExMSwuLGFkZE5BID0gVCkKIyBSVUxFIChBKTogSUYgcTRyMTE9VFJVRSwgaXQgbWVhbnMgeW91IGhhdmUgbm8gYXBwcy4gU28gdGhhdCBtZWFucyBxMTEgaGFzIHRvIGVxdWFsIDYsIGkuZS4gTk9ORS4gRGF0YSBzaG93cyB0aGlzIGlzIHZpb2xhdGVkLiBDb3JyZWN0aW5nIHVzaW5nIHRoaXMgcnVsZS4KZGZfbnVtcyRxMTFbZGZfbnVtcyRxNHIxMT09VFJVRV0gPC0gNgpkZl9udW1zICU+JSB4dGFicyh+cTRyMTErcTExLC4sYWRkTkEgPSBUKQpgYGAKCiMjIFNtYWxsIGNoYW5nZXMKClNpbmNlIHExMSBjYW4gYmUgb3JkaW5hbCwgIm5vbmUiIHNob3VsZCBlcXVhbCAwIGluc3RlYWQgb2YgNiB0byBwcmVzZXJ2ZSBvcmRpbmFsaXR5CmBgYHtyfQojIFJVTEUgKEIpOiBTZXQgcTExPTYgdG8gcTExPTAKZGZfbnVtcyRxMTFbZGZfbnVtcyRxMTE9PTZdIDwtIDAKZGZfbnVtcyAlPiUgeHRhYnMofnExMSwuLCBhZGROQSA9IFQpCmBgYAoKJ0RvbnQga25vdycgZG9lc24ndCBhZGQgdmFsdWUuIFBlcmhhcHMgdGhlc2UgY2FuIGJlIHNldCB0byBgTkFgIGFuZCB0aGVuIGltcHV0ZWQgdXNpbmcgYG1pY2VgLgoKYGBge3J9CiMgUlVMRSAoQyk6IFNldCBxMTEgRG9udCBrbm93IHRvIE5BCmRmX251bXMkcTExW2RmX251bXMkcTExPT0wXSA8LSBOQQpkZl9udW1zICU+JSB4dGFicyh+cTExLC4sIGFkZE5BID0gVCkKYGBgCgpgYGB7cn0KIyBSVUxFIChEKTogQWxsIE5BIHZhbHVlcyBmb3IgcTEyIHNldCB0byA2LCBzaW5jZSBJJ20gYXBwcm94aW1hdGluZyB0aGF0IGlmIHlvdSBkb24ndCBoYXZlIGFueSBhcHBzLCBtaWdodCBhcyB3ZWxsIGNvdWxkIGFzIGZyZWU/CmRmX251bXMkcTEyW2lzLm5hKGRmX251bXMkcTEyKV0gPC0gNgpkZl9udW1zICU+JSB4dGFicyh+cTEyLC4sIGFkZE5BID0gVCkKYGBgCgpgYGB7cn0KbWFwX2ludChkZl9udW1zLH5zdW0oaXMubmEoLngpKSkgJT4lIHNvcnQoKSAlPiUgdGFpbCgzKSAlPiUgYmFyY2hhcnQobWFpbj0nTWlzc2luZyB2YWx1ZXMnKQpgYGAKCgojIyBJbXB1dGluZyB1c2luZyBgbWljZWAKYGBge3J9Cm1hcF9kZihkZl9udW1zLH5hcy5mYWN0b3IoLngpKSAlPiUgCiAgbWljZTo6bWljZShwcmludEZsYWcgPSBULCBtID0gNSwgbWV0aG9kID0gJ3JmJykgLT4gbWljZUZpdApkZl9udW1zIDwtIHRibF9kZihtaWNlOjpjb21wbGV0ZShtaWNlRml0KSkKYGBgCgojIEJpIFBsb3RzCgpgYGB7cn0KIyBxdWVzdGlvbnNfdG9fY29uc29saWRhdGUgPC0gYygncTEzJywncTI0JywncTI1JywncTI2JykKIyBwbG90X2JpX3Bsb3RzKGRmX251bXMgJT4lIGRwbHlyOjpzZWxlY3QoY29udGFpbnMocXVlc3Rpb25zX3RvX2NvbnNvbGlkYXRlWzFdKSkscXVlc3Rpb25zX3RvX2NvbnNvbGlkYXRlWzFdKQojIHBsb3RfYmlfcGxvdHMoZGZfbnVtcyAlPiUgZHBseXI6OnNlbGVjdChjb250YWlucyhxdWVzdGlvbnNfdG9fY29uc29saWRhdGVbMl0pKSxxdWVzdGlvbnNfdG9fY29uc29saWRhdGVbMl0sIHhsaW09YygwLC4wNSksIHlsaW09YygtMC4wMSwwLjAwMikpCiMgcGxvdF9iaV9wbG90cyhkZl9udW1zICU+JSBkcGx5cjo6c2VsZWN0KGNvbnRhaW5zKHF1ZXN0aW9uc190b19jb25zb2xpZGF0ZVszXSkpLHF1ZXN0aW9uc190b19jb25zb2xpZGF0ZVszXSkKIyBwbG90X2JpX3Bsb3RzKGRmX251bXMgJT4lIGRwbHlyOjpzZWxlY3QoY29udGFpbnMocXVlc3Rpb25zX3RvX2NvbnNvbGlkYXRlWzRdKSkscXVlc3Rpb25zX3RvX2NvbnNvbGlkYXRlWzRdLCB4bGltPWMoMCwwLjA1KSx5bGltPWMoLTAuMDExLDAuMDA1KSkKYGBgCgojIERhdGEgUHJlcAoKIyMgU3ViIGdyb3VwaW5nCgpgYGB7cn0KZGZfbnVtcyA8LSBtYXBfZGYoZGZfbnVtcyx+YXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoLngpKSkKZGZfbnVtc19hZGogPC0gZGZfbnVtcyAlPiUgIAogIGFkanVzdF9xMTMoKSAlPiUgCiAgYWRqdXN0X3EyNCgpICU+JSAKICBhZGp1c3RfcTI1KCkgJT4lIAogIGFkanVzdF9xMjYoKSAlPiUgCiAgYWRqdXN0X3EyKCkgJT4lIAogIGFkanVzdF9xNCgpICU+JSAKICBhZGp1c3RfcmFjZSgpICU+JSAKICBhZGp1c3RfZ2VuZGVyKCkgJT4lIAogIGFkanVzdF9tYXJpdGFsKCkgJT4lIAogIGFkanVzdF9pbmNvbWUoKSAlPiUKICBhZGp1c3RfYWdlKCkgJT4lIAogIGFkanVzdF9xMTEoKSAlPiUgCiAgYWRqdXN0X25hbWVzKCkgJT4lIAogIGFkanVzdF9jaGlsZHJlbigpCgpnbGltcHNlKGRmX251bXNfYWRqKQpgYGAKCiMjIFNlbGVjdGlvbiBvZiBiYXNpcyB2YXJpYWJsZXMKCmBgYHtyfQpzZXQxIDwtIGMoCiAgJ3ExX2FnZScsCiAgIyAncTExX2FwcG51bScsCiAgIyAncTEyX2ZyZWVhcHBwYycsCiAgJ3E0OF9lZHUnLAogICdxNDlfbWFyaXRhbCcsCiAgJ3E1MHIxX25vY2hpbGQnLAogICdxNTZfaW5jb21lJywKICAjICdxNTdfbWYnLAogICMgJ3ExM192aXNpdGZyZXFfc29jaWFsJywKICAjICdxMTNfdmlzaXRmcmVxX211c2ljJywKICAjICdxMTNfdmlzaXRmcmVxX3ZpZGVvJywKICAncTI0X3RlY2hfcG9zYXR0JywKICAncTI0X3RlY2hfZW50ZXInLAogICdxMjRfdGVjaF9jb21tJywKICAncTI0X3RlY2hfbmVnYXR2JywKICAjICdxMjVfcHJzbmx0eV9sZWFkZXInLAogICMgJ3EyNV9wcnNubHR5X3Jpc2snLAogICMgJ3EyNV9wcnNubHR5X2RyaXZlJywKICAjICdxMjVfcHJzbmx0eV9mb2xsb3dlcicsCiAgJ3EyNl9zaG9wc2F2dnlfYmFyZ2FpbicsCiAgJ3EyNl9zaG9wc2F2dnlfYnJhbmRzJywKICAncTI2X3Nob3BzYXZ2eV9lYXJuMnNwZW5kJywKICAncTI2X3Nob3BzYXZ2eV9hcHBsb3ZlcicsCiAgJ3EyNl9zaG9wc2F2dnlfY2hpbGRyZW4nLAogICdxMl9hcHBsZScsCiAgJ3EyX2FuZHJpb2QnLAogICdxMl93aW5kb3dzJywKICAjICdxMl90YWJsZXQnLAogICMgJ3EyX290aGVyJywKICAjICdxNF91c2VfbXVzaWNfYXBwcycsCiAgIyAncTRfdXNlX3R2X2FwcHMnLAogICMgJ3E0X3VzZV9nYW1lX2FwcHMnLAogICMgJ3E0X3VzZV9zb2NpYWxfYXBwcycsCiAgIyAncTRfdXNlX25ld3NfYXBwcycsCiAgIyAncTRfdXNlX3Nob3BfYXBwcycsCiAgIyAncTRfdXNlX25vbmVfYXBwcycsCiAgJ3E1NF93aGl0ZScsCiAgJ3E1NF9ibGFjaycsCiAgJ3E1NF9hc2lhbicsCiAgJ3E1NF9oYXdhaScsCiAgJ3E1NF9uYXRpdmUnLAogICMgJ3E1NF9vdGhlcicsCiAgJ3E1NV9sYXRpbm8nCiAgKQpzZXQyIDwtIGMoCiAgJ3ExX2FnZScsCiAgIyAncTExX2FwcG51bScsCiAgJ3ExMl9mcmVlYXBwcGMnLAogICdxNDhfZWR1JywKICAncTQ5X21hcml0YWwnLAogICdxNTByMV9ub2NoaWxkJywKICAncTU2X2luY29tZScsCiAgIyAncTU3X21mJywKICAncTEzX3Zpc2l0ZnJlcV9zb2NpYWwnLAogICdxMTNfdmlzaXRmcmVxX211c2ljJywKICAncTEzX3Zpc2l0ZnJlcV92aWRlbycsCiAgJ3EyNF90ZWNoX3Bvc2F0dCcsCiAgJ3EyNF90ZWNoX2VudGVyJywKICAncTI0X3RlY2hfY29tbScsCiAgJ3EyNF90ZWNoX25lZ2F0dicsCiAgJ3EyNV9wcnNubHR5X2xlYWRlcicsCiAgJ3EyNV9wcnNubHR5X3Jpc2snLAogICdxMjVfcHJzbmx0eV9kcml2ZScsCiAgJ3EyNV9wcnNubHR5X2ZvbGxvd2VyJywKICAncTI2X3Nob3BzYXZ2eV9iYXJnYWluJywKICAncTI2X3Nob3BzYXZ2eV9icmFuZHMnLAogICdxMjZfc2hvcHNhdnZ5X2Vhcm4yc3BlbmQnLAogICdxMjZfc2hvcHNhdnZ5X2FwcGxvdmVyJywKICAncTI2X3Nob3BzYXZ2eV9jaGlsZHJlbicsCiAgIyAncTJfYXBwbGUnLAogICMgJ3EyX2FuZHJpb2QnLAogICMgJ3EyX3dpbmRvd3MnLAogICMgJ3EyX3RhYmxldCcsCiAgIyAncTJfb3RoZXInLAogICMgJ3E0X3VzZV9tdXNpY19hcHBzJywKICAjICdxNF91c2VfdHZfYXBwcycsCiAgIyAncTRfdXNlX2dhbWVfYXBwcycsCiAgIyAncTRfdXNlX3NvY2lhbF9hcHBzJywKICAjICdxNF91c2VfbmV3c19hcHBzJywKICAjICdxNF91c2Vfc2hvcF9hcHBzJywKICAjICdxNF91c2Vfbm9uZV9hcHBzJywKICAncTU0X3doaXRlJywKICAncTU0X2JsYWNrJywKICAncTU0X2FzaWFuJywKICAncTU0X2hhd2FpJywKICAncTU0X25hdGl2ZScsCiAgIyAncTU0X290aGVyJywKICAncTU1X2xhdGlubycKICApCnNldDMgPC0gYygKICAncTFfYWdlJywKICAncTExX2FwcG51bScsCiAgJ3ExMl9mcmVlYXBwcGMnLAogICdxNDhfZWR1JywKICAncTQ5X21hcml0YWwnLAogICdxNTByMV9ub2NoaWxkJywKICAncTU2X2luY29tZScsCiAgJ3E1N19tZicsCiAgIyAncTEzX3Zpc2l0ZnJlcV9zb2NpYWwnLAogICMgJ3ExM192aXNpdGZyZXFfbXVzaWMnLAogICMgJ3ExM192aXNpdGZyZXFfdmlkZW8nLAogICMgJ3EyNF90ZWNoX3Bvc2F0dCcsCiAgIyAncTI0X3RlY2hfZW50ZXInLAogICMgJ3EyNF90ZWNoX2NvbW0nLAogICMgJ3EyNF90ZWNoX25lZ2F0dicsCiAgIyAncTI1X3Byc25sdHlfbGVhZGVyJywKICAjICdxMjVfcHJzbmx0eV9yaXNrJywKICAjICdxMjVfcHJzbmx0eV9kcml2ZScsCiAgIyAncTI1X3Byc25sdHlfZm9sbG93ZXInLAogICdxMjZfc2hvcHNhdnZ5X2JhcmdhaW4nLAogICdxMjZfc2hvcHNhdnZ5X2JyYW5kcycsCiAgJ3EyNl9zaG9wc2F2dnlfZWFybjJzcGVuZCcsCiAgJ3EyNl9zaG9wc2F2dnlfYXBwbG92ZXInLAogICdxMjZfc2hvcHNhdnZ5X2NoaWxkcmVuJywKICAncTJfYXBwbGUnLAogICdxMl9hbmRyaW9kJywKICAncTJfd2luZG93cycsCiAgJ3EyX3RhYmxldCcsCiAgJ3EyX290aGVyJywKICAncTRfdXNlX211c2ljX2FwcHMnLAogICdxNF91c2VfdHZfYXBwcycsCiAgJ3E0X3VzZV9nYW1lX2FwcHMnLAogICdxNF91c2Vfc29jaWFsX2FwcHMnLAogICdxNF91c2VfbmV3c19hcHBzJywKICAncTRfdXNlX3Nob3BfYXBwcycsCiAgJ3E0X3VzZV9ub25lX2FwcHMnCiAgIyAncTU0X3doaXRlJywKICAjICdxNTRfYmxhY2snLAogICMgJ3E1NF9hc2lhbicsCiAgIyAncTU0X2hhd2FpJywKICAjICdxNTRfbmF0aXZlJywKICAjICdxNTRfb3RoZXInLAogICMgJ3E1NV9sYXRpbm8nCiAgKQpzZXQ0IDwtIGMoCiAgJ3ExX2FnZScsCiAgIyAncTExX2FwcG51bScsCiAgIyAncTEyX2ZyZWVhcHBwYycsCiAgIyAncTQ4X2VkdScsCiAgJ3E0OV9tYXJpdGFsJywKICAncTUwcjFfbm9jaGlsZCcsCiAgJ3E1Nl9pbmNvbWUnLAogICdxNTdfbWYnLAogICdxMTNfdmlzaXRmcmVxX3NvY2lhbCcsCiAgJ3ExM192aXNpdGZyZXFfbXVzaWMnLAogICdxMTNfdmlzaXRmcmVxX3ZpZGVvJywKICAncTI0X3RlY2hfcG9zYXR0JywKICAncTI0X3RlY2hfZW50ZXInLAogICdxMjRfdGVjaF9jb21tJywKICAncTI0X3RlY2hfbmVnYXR2JywKICAncTI1X3Byc25sdHlfbGVhZGVyJywKICAncTI1X3Byc25sdHlfcmlzaycsCiAgJ3EyNV9wcnNubHR5X2RyaXZlJywKICAncTI1X3Byc25sdHlfZm9sbG93ZXInLAogICdxMjZfc2hvcHNhdnZ5X2JhcmdhaW4nLAogICdxMjZfc2hvcHNhdnZ5X2JyYW5kcycsCiAgJ3EyNl9zaG9wc2F2dnlfZWFybjJzcGVuZCcsCiAgJ3EyNl9zaG9wc2F2dnlfYXBwbG92ZXInLAogICdxMjZfc2hvcHNhdnZ5X2NoaWxkcmVuJwogICMgJ3EyX2FwcGxlJywKICAjICdxMl9hbmRyaW9kJywKICAjICdxMl93aW5kb3dzJywKICAjICdxMl90YWJsZXQnLAogICMgJ3EyX290aGVyJywKICAjICdxNF91c2VfbXVzaWNfYXBwcycsCiAgIyAncTRfdXNlX3R2X2FwcHMnLAogICMgJ3E0X3VzZV9nYW1lX2FwcHMnLAogICMgJ3E0X3VzZV9zb2NpYWxfYXBwcycsCiAgIyAncTRfdXNlX25ld3NfYXBwcycsCiAgIyAncTRfdXNlX3Nob3BfYXBwcycsCiAgIyAncTRfdXNlX25vbmVfYXBwcycKICAjICdxNTRfd2hpdGUnLAogICMgJ3E1NF9ibGFjaycsCiAgIyAncTU0X2FzaWFuJywKICAjICdxNTRfaGF3YWknLAogICMgJ3E1NF9uYXRpdmUnLAogICMgJ3E1NF9vdGhlcicsCiAgIyAncTU1X2xhdGlubycKICApCmBgYAoKYGBge3J9CmRmX251bXNfYWRqX2JhY2t1cCA8LSBkZl9udW1zX2FkagpgYGAKYGBge3J9CmRmX251bXNfYWRqIDwtIGRmX251bXNfYWRqX2JhY2t1cApgYGAKCmBgYHtyfQpkZl9udW1zX2FkaiA8LSBkZl9udW1zX2FkaiAlPiUgZHBseXI6OnNlbGVjdChvbmVfb2Yoc2V0NCkpCmBgYAoKCiMgU2NhbGluZwpgYGB7cn0Kc2NhbGluZ193YW50ZWQgPC0gVAptaW5tYXhfd2FudGVkIDwtIEYKaWYgKHNjYWxpbmdfd2FudGVkKSB7CiAgZGZfbnVtc19hZGpzY2FsZWQgPC0gc2NhbGUoZGZfbnVtc19hZGopCiAgY2VudGVycyA8LSBhdHRyaWJ1dGVzKGRmX251bXNfYWRqc2NhbGVkKVtbM11dCiAgc3ByZWFkcyA8LSBhdHRyaWJ1dGVzKGRmX251bXNfYWRqc2NhbGVkKVtbNF1dCiAgZGZfbnVtc19hZGpzY2FsZWQgPC0gdGJsX2RmKGRmX251bXNfYWRqc2NhbGVkKQp9CmlmKG1pbm1heF93YW50ZWQpewogIGRmX251bXNfYWRqc2NhbGVkIDwtIG1hcF9kZihkZl9udW1zX2Fkaiwgfm1pbm1heCgueCkpCn0KaWYoIXNjYWxpbmdfd2FudGVkICYgIW1pbm1heF93YW50ZWQpewogIGRmX251bXNfYWRqc2NhbGVkIDwtIGRmX251bXNfYWRqCn0KaGVhZChkZl9udW1zX2FkanNjYWxlZCkKYGBgCgojIENvcnJlbGF0aW9uIFBsb3QKYGBge3J9CmRmX251bXNfYWRqc2NhbGVkICU+JSBjb3IoKSAlPiUgY29ycnBsb3QobWV0aG9kID0gJ3NoYWRlJyx0bC5jb2wgPSAnYmxhY2snLHRsLmNleCA9IC45LCBvcmRlciA9ICdoY2x1c3QnLCBoY2x1c3QubWV0aG9kID0gJ3dhcmQuRDInKQpgYGAKCiMgRGlzc2ltaWxhcml0eSBDYWxjdWxhdGlvbnMKCmBgYHtyfQojIG9yZGVyZWQ9YygxOjQsMTEsMTM6MjgpCiMgc3ltbV9iaW49Yyg2OjEwLDEyLDI5OjQ3KQojIGRmX251bXNfYWRqc2NhbGVkW29yZGVyZWRdIDwtIG1hcF9kZihkZl9udW1zX2FkanNjYWxlZFtvcmRlcmVkXSx+YXMub3JkZXJlZCgueCkpCiMgZGZfbnVtc19hZGpzY2FsZWRbc3ltbV9iaW5dIDwtIG1hcF9kZihkZl9udW1zX2FkanNjYWxlZFtzeW1tX2Jpbl0sfmFzLmZhY3RvcigueCkpCmRpc3RNYXQgPC0gZGFpc3koZGZfbnVtc19hZGpzY2FsZWQpCmBgYAoKCiMgU2ltcGxlIGNsdXN0ZXJpbmcKCiMjIEggY2x1c3QKCiMjIyBIb3cgY29waGVuZXRpYyBjaGFuZ2VzIHdpdGggY2x1c3RlcmluZyBtZXRob2Q/CmBgYHtyfQptZXRob2RzIDwtIGMoJ2NvbXBsZXRlJywnYXZlcmFnZScsJ3dhcmQuRCcsJ3dhcmQuRDInLCdtZWRpYW4nLCdtY3F1aXR0eScsJ2NlbnRyb2lkJykKbWV0aG9kX3ZzX2NvcCA8LSBtYXBfZGJsKG1ldGhvZHMsfmNvcihjb3BoZW5ldGljKGhjbHVzdChkID0gZGlzdE1hdCwgbWV0aG9kID0gLngpKSwgZGlzdE1hdCkpCm5hbWVzKG1ldGhvZF92c19jb3ApIDwtIG1ldGhvZHMKYmFyY2hhcnQoc29ydChtZXRob2RfdnNfY29wKSkKYGBgCgpgYGB7cn0KayA9IDYKaGNsdXN0Rml0IDwtIGhjbHVzdChkID0gZGlzdE1hdCwgbWV0aG9kID0gJ3dhcmQuRCcpCnBsb3QoaGNsdXN0Rml0LCBsYWJlbHMgPSBGKQpyZWN0LmhjbHVzdChoY2x1c3RGaXQsIGs9aywgYm9yZGVyPSJyZWQiKQpgYGAKCgpgYGB7cn0KaGNsdXN0X3NlZ21lbnRzIDwtIGN1dHJlZShoY2x1c3RGaXQsIGsgPSBrKQp0YWJsZShoY2x1c3Rfc2VnbWVudHMpCmNsdXNwbG90KGRmX251bXNfYWRqc2NhbGVkLCBoY2x1c3Rfc2VnbWVudHMsIGNvbG9yPVRSVUUsIHNoYWRlPVRSVUUsIGxhYmVscz00LCBsaW5lcz0wLCBtYWluPSJIQ2x1c3QgcGxvdCIpCmBgYAoKYGBge3J9CnNlZy5zdW1tKGRmX251bXNfYWRqLCBoY2x1c3Rfc2VnbWVudHMpIC0+IGNlbnRyb2lkcwpjZW50cm9pZHMKYGBgCgpgYGB7cn0KY3V0Rml0IDwtIGN1dHJlZShoY2x1c3RGaXQsIGspCnBsb3Qoc2lsaG91ZXR0ZShjdXRGaXQsZGlzdE1hdCkpCmBgYApgYGB7cn0KayA8LSAyOjEwCndpZHRocyA8LSBOVUxMCmZvcihrXyBpbiBrKXsKICBoY2x1c3RGaXQgPC0gaGNsdXN0KGQgPSBkaXN0TWF0LCBtZXRob2QgPSAnd2FyZC5EJykKICBjdXRGaXQgPC0gY3V0cmVlKGhjbHVzdEZpdCwga18pCiAgd2lkdGhzIDwtIGMod2lkdGhzLG1lYW4oc2lsaG91ZXR0ZShjdXRGaXQsZGlzdE1hdClbLCdzaWxfd2lkdGgnXSkpCn0KcGxvdChrLHdpZHRocyx0eXBlPSdiJykKY2JpbmQoayx3aWR0aHMpCmBgYAoKCiMjIEstbWVhbnMKCiMjIyBIb3cgbWFueSBjbHVzdGVycyB0byB1c2U/CgpgYGB7cn0Kd3NzcGxvdCA8LSBmdW5jdGlvbihudW1zdWIsIG5jPTE1LCBzZWVkPTExMTEpIHsKICB3c3MgPC0gKG5yb3cobnVtc3ViKS0xKSpzdW0oYXBwbHkobnVtc3ViLDIsdmFyKSkKICBmb3IgKGkgaW4gMjpuYykgewogICAgc2V0LnNlZWQoc2VlZCkKICAgIHdzc1tpXSA8LSBzdW0oa21lYW5zKG51bXN1YiwgY2VudGVycz1pLCBpdGVyLm1heCA9IDFlNCkkd2l0aGluc3MpfQogIHBsb3QoMTpuYywgd3NzLCB0eXBlPSJiIiwgeGxhYj0iTnVtYmVyIG9mIENsdXN0ZXJzIiwKICAgICAgIHlsYWI9IldpdGhpbiBncm91cHMgc3VtIG9mIHNxdWFyZXMiKX0Kd3NzcGxvdChkZl9udW1zX2FkanNjYWxlZCkKYGBgCgojIyMgU29sdmluZyB0aGUgay1tZWFucyBtb2RlbAoKYGBge3J9CmsgPC0gMjoxMAp3aWR0aHMgPC0gTlVMTApmb3Ioa18gaW4gayl7CiAgY2x1c3RlcnJlc3VsdHMgPC0ga21lYW5zKHggPSBkZl9udW1zX2FkanNjYWxlZCwgY2VudGVycyA9IGtfLCBuc3RhcnQgPSAzMCkKICB3aWR0aHMgPC0gYyh3aWR0aHMsbWVhbihzaWxob3VldHRlKGNsdXN0ZXJyZXN1bHRzJGNsdXN0ZXIsZGlzdE1hdClbLCdzaWxfd2lkdGgnXSkpCn0KcGxvdChrLHdpZHRocyx0eXBlPSdiJykKY2JpbmQoayx3aWR0aHMpCmBgYAoKYGBge3J9CiMgVXNpbmcgY2x1c3RlciBjZW50ZXJzIGZyb20gaGNsdXN0OgpzZWcuc3VtbShkZl9udW1zX2FkanNjYWxlZCwgaGNsdXN0X3NlZ21lbnRzKSAtPiBrbWVhbnNfY2VudHJvaWRzCmNsdXN0ZXJyZXN1bHRzIDwtIGttZWFucyh4ID0gZGZfbnVtc19hZGpzY2FsZWQsIGNlbnRlcnMgPSBrbWVhbnNfY2VudHJvaWRzWywtMV0pCnJzcXVhcmUgPC0gY2x1c3RlcnJlc3VsdHMkYmV0d2VlbnNzL2NsdXN0ZXJyZXN1bHRzJHRvdHNzCmNhdCgnXG5XaXRoaW4gU1M6JyxjbHVzdGVycmVzdWx0cyR3aXRoaW5zcywnIFNpemVzOlxuJyxjbHVzdGVycmVzdWx0cyRzaXplLCdcbnJzcTonLCByc3F1YXJlKQpjbHVzcGxvdChkZl9udW1zX2FkanNjYWxlZCwgY2x1c3RlcnJlc3VsdHMkY2x1c3RlciwgY29sb3I9VFJVRSwgc2hhZGU9VFJVRSwgbGFiZWxzPTQsIGxpbmVzPTAsIG1haW49IkstbWVhbnMgY2x1c3RlciBwbG90IikKcGxvdChzaWxob3VldHRlKGNsdXN0ZXJyZXN1bHRzJGNsdXN0ZXIsZGlzdE1hdCkpCgojIFVzaW5nIG51bWJlciBvZiBjbHVzdGVycyArIHJhbmRvbSBzdGFydHMKa19rbWVhbnMgPSA2CmNsdXN0ZXJyZXN1bHRzIDwtIGttZWFucyh4ID0gZGZfbnVtc19hZGpzY2FsZWQsIGNlbnRlcnMgPSBrX2ttZWFucykKcnNxdWFyZSA8LSBjbHVzdGVycmVzdWx0cyRiZXR3ZWVuc3MvY2x1c3RlcnJlc3VsdHMkdG90c3MKY2F0KCdcbldpdGhpbiBTUzonLGNsdXN0ZXJyZXN1bHRzJHdpdGhpbnNzLCcgU2l6ZXM6XG4nLGNsdXN0ZXJyZXN1bHRzJHNpemUsJ1xucnNxOicsIHJzcXVhcmUpCmNsdXNwbG90KGRmX251bXNfYWRqc2NhbGVkLCBjbHVzdGVycmVzdWx0cyRjbHVzdGVyLCBjb2xvcj1UUlVFLCBzaGFkZT1UUlVFLCBsYWJlbHM9NCwgbGluZXM9MCwgbWFpbj0iSy1tZWFucyBjbHVzdGVyIHBsb3QiKQpwbG90KHNpbGhvdWV0dGUoY2x1c3RlcnJlc3VsdHMkY2x1c3RlcixkaXN0TWF0KSkKYGBgCgpgYGB7cn0Kc2VnLnN1bW0oZGZfbnVtc19hZGosIGNsdXN0ZXJyZXN1bHRzJGNsdXN0ZXIpIC0+IHNlZ3N1bW1hcnlfcmVzdWx0cwpzZWdzdW1tYXJ5X3Jlc3VsdHMgJT4lIHdyaXRlX2NzdihwYXRoID0gJy4uL3JlcG9ydHMva21lYW5zX3Jlc3VsdHMuY3N2JywgY29sX25hbWVzID0gVCkKc2Vnc3VtbWFyeV9yZXN1bHRzCmBgYApgYGB7cn0Ka21lYW5zX3Jlc3VsdHMgPC0gZGZfbnVtc19hZGogJT4lIAogIG11dGF0ZShjbHVzdGVyID0gY2x1c3RlcnJlc3VsdHMkY2x1c3RlcikKCnB1cnJyOjptYXAyKGttZWFuc19yZXN1bHRzLCBuYW1lcyhrbWVhbnNfcmVzdWx0cyksCiAgICAgICAgICAgIH5id3Bsb3QoY2x1c3Rlcn4ueCwga21lYW5zX3Jlc3VsdHMsCiAgICAgICAgICAgICAgICAgICAgbWFpbj0ueSkpCmBgYAoKIyMgUEFNCgpgYGB7cn0KcGFtRml0cyA8LSB0aWJibGUoa19wYW0gPSAyOjEwKQpwYW1GaXRzJHBhbUZpdHMgPC0gbWFwKHBhbUZpdHMka19wYW0sIH5wYW0oZGZfbnVtc19hZGpzY2FsZWQsIGsgPSAueCkpCnBhbUZpdHMkc2lsX2F2Z193aWR0aCA8LSBtYXBfZGJsKHBhbUZpdHMkcGFtRml0cyx+Lngkc2lsaW5mbyRhdmcud2lkdGgpCnBhbUZpdHMKYGBgCgpgYGB7cn0KcGFtRml0cyAlPiUgCiAgeHlwbG90KHNpbF9hdmdfd2lkdGh+YXMuZmFjdG9yKGtfcGFtKSwuLHR5cGU9J2InKQpgYGAKCmBgYHtyfQpwbG90KHBhbUZpdHMkcGFtRml0c1tbMV1dKQpgYGAKCmBgYHtyfQpzZWcuc3VtbShkZl9udW1zX2FkaiwgcGFtRml0cyRwYW1GaXRzW1sxXV0kY2x1c3RlcmluZykKYGBgCgojIE1vZGVsIGJhc2VkCgpgYGB7cn0KbWNsdXN0Rml0cyA8LSB0aWJibGUobWNsdXN0X2NsdXN0ZXJzPTI6OCkKbWNsdXN0Rml0cyRtY2x1c3RGaXRzIDwtIG1hcChtY2x1c3RGaXRzJG1jbHVzdF9jbHVzdGVycywgfk1jbHVzdChkZl9udW1zX2FkanNjYWxlZCwgRyA9IC54KSkKbWNsdXN0Rml0cyRiaWMgPC0gbWFwX2RibChtY2x1c3RGaXRzJG1jbHVzdEZpdHMsIH4ueFtbJ2JpYyddXSkKbWNsdXN0Rml0cyRsb2dsaWsgPC0gbWFwX2RibChtY2x1c3RGaXRzJG1jbHVzdEZpdHMsIH4ueFtbJ2xvZ2xpayddXSkKbWNsdXN0Rml0cwpgYGAKCmBgYHtyfQptY2x1c3RGaXRzICU+JSAKICB4eXBsb3QoYmljK2xvZ2xpa35hcy5mYWN0b3IobWNsdXN0X2NsdXN0ZXJzKSwuLCBhdXRvLmtleSA9IFQsIHR5cGUgPSAnYicpCmBgYAoKYGBge3J9CnN1bW1hcnkobWNsdXN0Rml0c1tbNCwnbWNsdXN0Rml0cyddXSkKYGBgCgpgYGB7cn0KbWNsdXN0X2NsdXN0ZXJzIDwtIG1jbHVzdEZpdHNbWzQsJ21jbHVzdEZpdHMnXV0kY2xhc3NpZmljYXRpb24KY2x1c3Bsb3QoZGZfbnVtc19hZGosIG1jbHVzdF9jbHVzdGVycywgY29sb3I9VFJVRSwgc2hhZGU9VFJVRSwgbGFiZWxzPTQsIGxpbmVzPTAsIG1haW49Ik0gQ2x1c3QgUGxvdCwgayA9IDQiKQpgYGAKCmBgYHtyfQpzZWcuc3VtbShkZl9udW1zX2FkaiwgbWNsdXN0X2NsdXN0ZXJzKQpgYGAKYGBge3J9Cm1jbHVzdF9kaXN0TWF0IDwtIGRhaXN5KGRmX251bXNfYWRqKQpwbG90KHNpbGhvdWV0dGUobWNsdXN0X2NsdXN0ZXJzLG1jbHVzdF9kaXN0TWF0KSkKYGBgCgo8IS0tICMjIHRzbmUgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSB0c25lRml0IDwtIFJ0c25lOjpSdHNuZShYID0gYXMubWF0cml4KGRmX251bXNfYWRqc2NhbGVkKSwgcGVycGxleGl0eSA9IDQwLCBtYXhfaXRlciA9IDUwMDAsIHBjYSA9IEZBTFNFLCBtb21lbnR1bSA9IDAuNzUpIC0tPgo8IS0tIHRzbmVGaXQgLS0+CjwhLS0gdG9QbG90IDwtIHRibF9kZih0c25lRml0JFkpIC0tPgo8IS0tIG5hbWVzKHRvUGxvdCkgPC0gYygnWCcsJ1knKSAtLT4KPCEtLSB4eXBsb3QoWH5ZLCBkYXRhID0gdG9QbG90KSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBkZl9udW1zX2FkaiAlPiUgYmluZF9jb2xzKHRvUGxvdCkgJT4lICAtLT4KPCEtLSAgIGxhdHRpY2U6Onh5cGxvdChZflgsZ3JvdXBzPXExM192aXNpdGZyZXFfdmlkZW8sZGF0YT0uLGF1dG8ua2V5PWxpc3QoY29sdW1ucz02KSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZGZfbnVtc19hZGogJT4lIGJpbmRfY29scyh0b1Bsb3QpICU+JSB3cml0ZV9jc3YocGF0aCA9ICcuLi9kYXRhL3RzbmVfb3V0LmNzdicsIGNvbF9uYW1lcyA9IFQpIC0tPgo8IS0tIGBgYCAtLT4KCg==